﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace LogExpert
{
	/// <summary>
	/// Handles rollover naming. The names built by the RolloverFilenameBuilder will be used
	/// to check if the file exist. Names will be built by incrmenting an index and decrementing a date.
	/// A configurable number of days in the past will be checked (date gaps may occur on days without log file activity).
	/// Date checking is only performed if the format pattern contains a date format. Index checking
	/// is only performed of the format pattern contains an index placeholder.
	/// </summary>
	public class RolloverFilenameHandler
	{
		private RolloverFilenameBuilder filenameBuilder;
		private ILogFileInfo logFileInfo;
		private MultifileOptions options;

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="filePath">The complete path of the logfile</param>
		/// <param name="options">Multifile option (e.g. format pattern)</param>
		public RolloverFilenameHandler(ILogFileInfo logFileInfo, MultifileOptions options)
		{
			this.options = options;
			this.logFileInfo = logFileInfo;
			this.filenameBuilder = new RolloverFilenameBuilder(this.options.FormatPattern);
			this.filenameBuilder.SetFileName(logFileInfo.FileName);
		}

		/// <summary>
		/// Returns a list of the built file names (complete path) which also exists on disk.
		/// The list is created by using the RolloverFilenameBuilder and checking for file existence.
		/// The first entry in the list contains the oldest file. The last entry contains the file given
		/// in the contructor.
		/// </summary>
		/// <returns></returns>
		public LinkedList<string> GetNameList()
		{
			LinkedList<string> fileList = new LinkedList<string>();
			string fileName = filenameBuilder.BuildFileName();
			string filePath = this.logFileInfo.DirectoryName + this.logFileInfo.DirectorySeparatorChar + fileName;
			fileList.AddFirst(filePath);
			bool found = true;
			while (found)
			{
				found = false;
				// increment index and check if file exists
				if (this.filenameBuilder.IsIndexPattern)
				{
					this.filenameBuilder.Index = this.filenameBuilder.Index + 1;
					fileName = filenameBuilder.BuildFileName();
					filePath = this.logFileInfo.DirectoryName + this.logFileInfo.DirectorySeparatorChar + fileName;
					if (FileExists(filePath))
					{
						fileList.AddFirst(filePath);
						found = true;
						continue;
					}
				}
				// if file with index isn't found or no index is in format pattern, decrement the current date
				if (this.filenameBuilder.IsDatePattern)
				{
					int tryCounter = 0;
					this.filenameBuilder.Index = 0;
					while (tryCounter < this.options.MaxDayTry)
					{
						this.filenameBuilder.DecrementDate();
						fileName = filenameBuilder.BuildFileName();
						filePath = this.logFileInfo.DirectoryName + this.logFileInfo.DirectorySeparatorChar + fileName;
						if (FileExists(filePath))
						{
							fileList.AddFirst(filePath);
							found = true;
							break;
						}
						else
						{
							tryCounter++;
						}
					}
				}
			}
			return fileList;
		}

		private bool FileExists(string filePath)
		{
			IFileSystemPlugin fs = PluginRegistry.GetInstance().FindFileSystemForUri(filePath);
			ILogFileInfo info = fs.GetLogfileInfo(filePath);
			return info.FileExists;
		}
	}
}